package com.netease.financial.base.suspendwindow;

import android.content.Context;
import android.graphics.PixelFormat;
import android.os.Handler;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;

import com.netease.financial.common.util.DensityUtil;
import com.netease.financial.common.util.NfsLog;

import java.lang.reflect.Field;

import cn.bingoogolapple.badgeview.BGABadgeImageView;

// 悬浮窗
public class SuspendWindow {

    private final String TAG = SuspendWindow.class.getSimpleName();

    private WindowManager mWindowManager;

    private BGABadgeImageView mChatBallView;

    private WindowManager.LayoutParams mChatBallParams;

    private boolean isChatBallAddToWindow = false;//小球是否添加了

    private int statusBarHeight;//系统状态栏的高度 
    private int screenWidth;
    private int screenHeight;
    private int mBallWidth;
    private int mBallHeight;
    public int[] src = new int[]{0, 0};//初始点
    private final int[] des = new int[]{0, 0};//左上角

    private Context mContext;
    private Handler mHandler;

    public SuspendWindow(Context context) {
        mContext = context;
    }

    private void init(Context context) {
        mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        mHandler = new Handler(context.getMainLooper());
        mBallWidth = mChatBallView.getDrawable().getIntrinsicWidth();
        mBallHeight = mChatBallView.getDrawable().getIntrinsicHeight();

        des[0] = mBallWidth / 2;
        des[1] = mBallHeight / 2;

        src[0] = getScreenWidth() - mBallWidth / 2;
        src[1] = (getScreenHeight() - getStatusBarHeight(context)) / 2;

        getChatBallParam(context);
    }

    public void setContentView(BGABadgeImageView contentView) {
        mChatBallView = contentView;
        init(mContext);
    }

    public void onConfigurationChanged() {
        if (getScreenWidth() != getWindowManager().getDefaultDisplay().getWidth()) {
            onScreenConfigurationChanged();
        }
    }

    private void onScreenConfigurationChanged() {
        float oldHPercent = (float) src[1] / (float) (screenHeight - getStatusBarHeight(mContext));

        int tmp = screenWidth;
        screenWidth = screenHeight;
        screenHeight = tmp;

        if (src[0] > getBallWidth() / 2)//在右边
        {
            src[0] = screenWidth - getBallWidth() / 2;
            getChatBallParam(mContext).x = src[0] - des[0];
        }
        src[1] = (int) (oldHPercent * (screenHeight - getStatusBarHeight(mContext)));
        getChatBallParam(mContext).y = src[1] - des[1];

        if (isChatBallAddToWindow) {
            mWindowManager.updateViewLayout(mChatBallView, getChatBallParam(mContext));
        }

        NfsLog.v(TAG, "onScreenConfigurationChanged sWidth:" + screenWidth + " sHeight:" + screenHeight);

    }

    private WindowManager getWindowManager() {
        return mWindowManager;
    }

    public int getStatusBarHeight(Context context) {
        if (statusBarHeight == 0) {
            try {
                Class<?> c = Class.forName("com.android.internal.R$dimen");
                Object o = c.newInstance();
                Field field = c.getField("status_bar_height");
                int x = (Integer) field.get(o);
                statusBarHeight = context.getResources().getDimensionPixelSize(x);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return statusBarHeight;
    }

    private int getScreenWidth() {
        if (screenWidth == 0) {
            screenWidth = mWindowManager.getDefaultDisplay().getWidth();
            screenHeight = mWindowManager.getDefaultDisplay().getHeight();
        }
        return screenWidth;
    }

    private int getScreenHeight() {
        if (screenHeight == 0) {
            screenWidth = mWindowManager.getDefaultDisplay().getWidth();
            screenHeight = mWindowManager.getDefaultDisplay().getHeight();
        }
        return screenHeight;
    }

    private int getBallWidth() {
        return mBallWidth;
    }

    private int getBallHeight() {
        return mBallHeight;
    }

    private int _lastX;
    private int _lastY;

    public void updateChatBall(MotionEvent event) {
        int _newLastX = (int) event.getRawX();
        int _newLastY = (int) event.getRawY() - getStatusBarHeight(mContext);
        boolean isDragEnd = (event.getAction() == MotionEvent.ACTION_UP) || (event.getAction() == MotionEvent.ACTION_CANCEL);
        if (Math.abs(_lastX - _newLastX) > 8 || Math.abs(_lastY - _newLastY) > 8) {
            _lastX = _newLastX;
            _lastY = _newLastY;

            mChatBallParams.x = _lastX - des[0];
            mChatBallParams.y = _lastY - des[1];
            mWindowManager.updateViewLayout(mChatBallView, mChatBallParams);
        }

        if (isDragEnd) {
            moveToEdge(_newLastX, _newLastY);
        }
    }

    private void moveToEdge(int _newLastX, int _newLastY) {
        _lastX = _newLastX;
        _lastY = _newLastY;

        int[] src = new int[]{_lastX, _lastY};
        final int[] des = new int[]{0, 0};

        _lastX = (_lastX <= (getScreenWidth()) / 2) ? getBallWidth() / 2 : getScreenWidth() - getBallWidth() / 2;
        if (_lastY < getBallHeight() / 2) {
            _lastY = getBallHeight() / 2;
        } else if (_lastY > getScreenHeight() - getBallHeight() / 2) {
            _lastY = getScreenHeight() - getBallHeight() / 2;
        }

        des[0] = _lastX;
        des[1] = _lastY;

        if (null != trimRunnable) {
            trimRunnable.stopRun();
        }
        trimRunnable = new TransAnimRunnable(src, des, 200, new Runnable() {

            @Override
            public void run() {

                mChatBallParams.x = des[0] - SuspendWindow.this.des[0];
                mChatBallParams.y = des[1] - SuspendWindow.this.des[1];

                mWindowManager.updateViewLayout(mChatBallView, mChatBallParams);
                SuspendWindow.this.src = des;
            }
        });
        mHandler.post(trimRunnable);
    }

    private WindowManager.LayoutParams getChatBallParam(Context context) {
        if (null == mChatBallParams) {
            mChatBallParams = new WindowManager.LayoutParams();
            mChatBallParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
            mChatBallParams.format = PixelFormat.RGBA_8888; // 设置图片格式，效果为背景透明
            mChatBallParams.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;

            mChatBallParams.width = getBallWidth();
            mChatBallParams.height = getBallHeight();
            mChatBallParams.gravity = Gravity.LEFT | Gravity.TOP; // 调整悬浮窗口至右侧中间
            mChatBallParams.x = src[0] - des[0];
//            mChatBallParams.y = src[1] - des[1];
            mChatBallParams.y = getScreenHeight() / 6;
        }
        return mChatBallParams;
    }

    public void showContentView(Context context) {
        mChatBallView.setVisibility(View.VISIBLE);

        if (!isChatBallAddToWindow) {
            mChatBallParams = getChatBallParam(context);
            mWindowManager.addView(mChatBallView, mChatBallParams);
            isChatBallAddToWindow = true;
        }
    }

    public void hideContentView() {
        if (isChatBallAddToWindow) {
            if (null != mChatBallView) {
                mWindowManager.removeView(mChatBallView);
            }
            isChatBallAddToWindow = false;
        }
    }

    private VibrateRunnable mVibrateRunnable;
    private TransAnimRunnable trimRunnable;

    // 收到消息时,小球左右抖动
    private class VibrateRunnable implements Runnable {
        final long end;
        final int oldX;
        long run;
        private int amplitude;

        public VibrateRunnable() {
            end = System.currentTimeMillis() + 500;
            oldX = (mChatBallParams.x = (src[0] <= (getScreenWidth()) / 2) ? 0 : getScreenWidth() - getBallWidth());
            amplitude = DensityUtil.dp2px(mContext, 25);
        }

        public void stopRun() {
            mHandler.removeCallbacks(this);
            getChatBallParam(mContext).x = oldX;
            mWindowManager.updateViewLayout(mChatBallView, mChatBallParams);
        }

        @Override
        public void run() {

            if ((run = (end - System.currentTimeMillis())) > 0) {
                int value = (int) (amplitude * Math.sin((float) 4 * Math.PI * (500 - run) / (float) 500));
                if (oldX > 0 && value < 0 || oldX <= 0 && value > 0) {
                    value = (-value);
                }

                getChatBallParam(mContext).x = oldX - value;
                mWindowManager.updateViewLayout(mChatBallView, mChatBallParams);
                mHandler.postDelayed(this, 20);
            } else {
                mHandler.removeCallbacks(this);
                getChatBallParam(mContext).x = oldX;
                mWindowManager.updateViewLayout(mChatBallView, mChatBallParams);
            }
        }
    }

    private class TransAnimRunnable implements Runnable {
        private int dx;
        private int dy;
        private int duration = 300;
        private long start;
        private long runMills = 0;
        private int[] srcLoc;
        private int[] desLoc;
        private Runnable run;

        public TransAnimRunnable(int[] srcLoc, int[] desLoc, Runnable run) {
            this(srcLoc, desLoc, 300, run);
        }

        public TransAnimRunnable(int[] srcLoc, int[] desLoc, int duration, Runnable run) {
            this.srcLoc = srcLoc;
            this.desLoc = desLoc;
            dx = desLoc[0] - srcLoc[0];
            dy = desLoc[1] - srcLoc[1];
            start = System.currentTimeMillis();
            this.duration = duration;
            this.run = run;
        }

        public void stopRun() {
            mHandler.removeCallbacks(this);
        }

        @Override
        public void run() {

            if ((runMills = (System.currentTimeMillis() - start)) < duration) {
                int _dx = (int) ((float) runMills * dx / (float) duration);
                int _dy = (int) ((float) runMills * dy / (float) duration);

                mChatBallParams.x = (srcLoc[0] + _dx) - des[0];
                mChatBallParams.y = (srcLoc[1] + _dy) - des[1];
                mWindowManager.updateViewLayout(mChatBallView, mChatBallParams);

                mHandler.postDelayed(this, 20);
            } else {
                mChatBallParams.x = desLoc[0] - des[0];
                mChatBallParams.y = desLoc[1] - des[1];
                mWindowManager.updateViewLayout(mChatBallView, mChatBallParams);

                if (null != run) {
                    run.run();
                }
                mHandler.removeCallbacks(this);
            }
        }
    }
}
